/**
 * 
 */
package com.gr.staffpm.pages.schedule;

import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gr.staffpm.gof.observer.Subscribable;
import com.gr.staffpm.gof.observer.Subscriber;
import com.gr.staffpm.google.utils.GCalUtils;
import com.gr.staffpm.model.StringModel;
import com.gr.staffpm.pages.schedule.model.Event;
import com.gr.staffpm.security.service.UserService;
import com.gr.staffpm.tasks.service.TaskService;

/**
 * @author Graham Rhodes 19 Mar 2011 19:15:03
 */
public class MonthView extends Panel implements Subscribable {

    @SpringBean(name = "taskService")
    private TaskService taskService;
    @SpringBean(name = "userService")
    private UserService userService;
    private static final long serialVersionUID = 1L;
    private final List<Subscriber> subscribers = new ArrayList<Subscriber>();
    private final RepeatingView dayNames = new RepeatingView("dayNames");
    private final RepeatingView weeks = new RepeatingView("weeks");
    private DateTime currentDate, viewStart, viewEnd;
    private final Schedule schedule;
    private final Logger log = LoggerFactory.getLogger(getClass());

    public MonthView(String id, Schedule schedule) {
        super(id);
        this.schedule = schedule;

        currentDate = new DateTime().withDayOfMonth(new DateTime().dayOfMonth().getMinimumValue());
        if (currentDate.getDayOfWeek() != 7)
            currentDate = currentDate.minusDays(currentDate.getDayOfWeek());

        updateView(currentDate);

        add(dayNames);
        add(weeks);

    }

    /**
     * updates the month view with the specified date
     * @param date
     *          a DateTime
     */
    void updateView(final DateTime date) {

        DateTime currDate = date;

        dayNames.removeAll();
        for (int i = 0; i < 7; i++) {
            final DateTime cDate = currDate;
            dayNames.addOrReplace(new Label(String.valueOf(i), new StringModel(currDate.toString("EEE"))) {

                private static final long serialVersionUID = 1L;

                @Override
                protected void onComponentTag(ComponentTag tag) {
                    tag.getAttributes().put("title", cDate.toString("EEEEE, MMMMM dd, yyyy"));
                    tag.getAttributes().put("class", "ext-cal-hd-day " + (cDate.equals(date) ? "ext-cal-day-first" : ""));
                }

            });
            currDate = currDate.plusDays(1);
        }

        DateTime calMonthStart = viewStart = date;
        DateTime calMonthEnd = viewEnd = calMonthStart.plusDays(7).withDayOfMonth(calMonthStart.plusDays(7).dayOfMonth().getMaximumValue());
        if (calMonthEnd.getDayOfMonth() != 6) {
            calMonthEnd = calMonthEnd.plusDays(6 - (calMonthEnd.getDayOfWeek() == 7 ? 0 : calMonthEnd.getDayOfWeek()));
        }
        Period weeksInMonth = new Period(calMonthStart, calMonthEnd, PeriodType.days());
        int numWeeks = ((weeksInMonth.getDays() + 1) / 7);
        int top = 0;
        final int height = 100 / numWeeks;
        weeks.removeAll();
        for (int i = 0; i < numWeeks; i++) {
            final int topI = top;
            DateTime weekStart = calMonthStart.plusWeeks(i);
            List<Event> weekEvents = taskService.getTasksDueBetweenForUser(schedule, userService.getCurrentUser(), weekStart, weekStart.plusDays(7));
            if (userService.getCurrentUser().isGcalEnabled() && (userService.getCurrentUser().getGcalAuth() != null)) {
                weekEvents.addAll(GCalUtils.getAndProcessGcalEvents(schedule, userService, weekStart, weekStart.plusDays(7)));
            } else if (userService.getCurrentUser().isGcalEnabled() && (userService.getCurrentUser().getGcalAuth() == null)) {
                log.info("You have not autorised staffpm to access your google account.");
            }
            weeks.addOrReplace(new WeekRow(weekStart.toString("ddMMyyyy"), false, weekStart, date.plusDays(7), weekEvents) {

                private static final long serialVersionUID = 1L;

                @Override
                protected void onComponentTag(ComponentTag tag) {
                    tag.getAttributes().put("style", "top: " + topI + "%; height: " + height + "%;");
                    tag.getAttributes().put("class", "ext-cal-wk-ct");
                }

            });
            top = top + height;
            weekStart = weekStart.plusDays(7);
        }

    }

    public DateTime getViewStart() {
        return viewStart;
    }

    public DateTime getViewEnd() {
        return viewEnd;
    }

    @Override
    public void addSubscriber(Subscriber subscriber) {
        subscribers.add(subscriber);
    }

    @Override
    public void notifySubscribers(Object object, AjaxRequestTarget target) {

    }
}
